home *** CD-ROM | disk | FTP | other *** search
/ Aminet 43 / Aminet 43 (2001)(GTI - Schatztruhe)[!][Jun 2001].iso / Aminet / comm / tcp / Amster-source.lha / Amster_Install / Source / navigator.c < prev    next >
C/C++ Source or Header  |  2001-03-14  |  21KB  |  748 lines

  1. /*
  2. ** Amster - Navigator
  3. ** Copyright © 2000-2001 by Jacob Laursen
  4. **
  5. ** This program is free software; you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation; either version 2 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program; if not, write to the Free Software
  17. ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18. */
  19.  
  20. #include "amster.h"
  21.  
  22. #include <proto/dos.h>
  23. #include <proto/utility.h>
  24.  
  25. #include "network.h"
  26.  
  27. #include <MUI/NListview_mcc.h>
  28. #include <MUI/textinput_mcc.h>
  29.  
  30. #include "amster_Cat.h"
  31.  
  32. #define NAPIGATOR_REQ "GET /servers.php?version=108 HTTP/1.0\r\n\r\n"
  33.  
  34. /* Global variables */
  35.  
  36. BOOL ServerListChanged = FALSE;
  37.  
  38. /* Private prototypes */
  39.  
  40. void LoadServerList(struct NavigatorData *data);
  41. void SaveServerList(struct NavigatorData *data);
  42. void MarkServerOnline(struct NavigatorData *data, char *server, unsigned short port);
  43. MUI_LIST_DISP_DECL(ServerListDisplay, struct ServerEntry *entry);
  44. MUI_NLIST_COMP_DECL(ServerListCompare);
  45. MUI_LIST_DEST_DECL(ServerListDestruct, struct ServerEntry *entry);
  46. MUI_HOOK_DECL(ServerString, Object *lala, APTR *contents);
  47. BOOL GetNapigatorList(struct NavigatorData *data);
  48. BOOL get_response(long sockfd, char *buf, int max);
  49. void UpdateFromNapigator(struct NavigatorData *data, char *list);
  50. void NapigatorAdd(struct NavigatorData *data, LONG argarray[]);
  51.  
  52.  
  53. MUI_DISPATCH(NavigatorDispatch)
  54. {
  55.     struct NavigatorData *data;
  56.     struct ServerEntry *entry;
  57.     char *buf;
  58.  
  59.     switch (msg->MethodID) {
  60.         case OM_NEW:
  61.             return(NavigatorNew(cl, obj, (APTR)msg));
  62.         case NAVI_CONNECT:
  63.             {
  64.             int port;
  65.             data = INST_DATA(cl, obj);
  66.  
  67.             if (gui_onlinestate > OFFLINE) nap_logout();
  68.             get(data->ST_Port,   MUIA_String_Integer,  &buf);
  69.             port = (int)buf;
  70.             if (port > 65535) port = 65535;
  71.             get(data->ST_Server, MUIA_String_Contents, &buf);
  72.             if (gui_onlinestate < CONNECTING) nap_login_fromlist(buf, port);
  73.             return NULL;
  74.             }
  75.         case NAVI_GETSERVER:
  76.             data = INST_DATA(cl, obj);
  77.             DoMethod(data->LV_Server, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &entry);
  78.             if (entry) {
  79.                 set(data->ST_Server,  MUIA_String_Contents, entry->Name);
  80.                 set(data->ST_Port,    MUIA_String_Integer,  entry->Port);
  81.                 set(data->ST_Comment, MUIA_String_Contents, entry->Comment);
  82.             }
  83.             return NULL;
  84.         case NAVI_ADDSERVER:
  85.             {
  86.             BOOL selected = FALSE;
  87.  
  88.             data = INST_DATA(cl, obj);
  89.             DoMethod(data->LV_Server, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &entry);
  90.             if (entry) selected = TRUE;    /* One entry is already selected */
  91.  
  92.             if (entry = malloc(sizeof(struct ServerEntry))) {
  93.                 entry->LastOnline = 0;
  94.                 if (selected) {
  95.                     /* We clear the fields instead of dublicating selected entry */
  96.                     entry->Name = strdup(MSG_NAVIGATOR_NEW);
  97.                     entry->Comment = strdup("");
  98.                     entry->Port = 8888;
  99.                 }
  100.                 else {
  101.                     get(data->ST_Server, MUIA_String_Contents, &buf);
  102.                     entry->Name = strdup(buf);
  103.                     get(data->ST_Port, MUIA_String_Integer, &buf);
  104.                     entry->Port = (unsigned short)buf;
  105.                     get(data->ST_Comment, MUIA_String_Contents, &buf);
  106.                     entry->Comment = strdup(buf);
  107.                 }
  108.                 DoMethod(data->LV_Server, MUIM_NList_InsertSingle, entry, MUIV_NList_Insert_Sorted);
  109.                 set(data->LV_Server, MUIA_NList_First, MUIV_NList_Active_Bottom);
  110. /*                DoMethod(data->LV_Server, MUIM_NList_Jump, MUIV_NList_Jump_Active);*/
  111.                 ServerListChanged = TRUE;
  112.             }
  113.             }
  114.             return NULL;
  115.         case NAVI_REMOVESERVER:
  116.             data = INST_DATA(cl, obj);
  117.             DoMethod(data->LV_Server, MUIM_NList_Remove, MUIV_NList_Remove_Active);
  118.             ServerListChanged = TRUE;
  119.             return NULL;
  120.         case NAVI_REDRAWSERVER:
  121.             {
  122.             struct ServerEntry *entry;
  123.             int port;
  124.             APTR *contents = (APTR)(((muimsg)msg)->arg1);
  125.             data = INST_DATA(cl, obj);
  126.  
  127.             DoMethod(data->LV_Server, MUIM_NList_GetEntry, MUIV_NList_GetEntry_Active, &entry);
  128.             if (entry) {
  129.                 switch ((u_long)*(contents+1)) {
  130.                     case 0:
  131.                         entry->Name = strdup(*contents);
  132.                         break;
  133.                     case 1:
  134.                         port = atoi(*contents);
  135.                         if (port < 65536) entry->Port = port;
  136.                         else entry->Port = 65535;
  137.                         break;
  138.                     case 2:
  139.                         entry->Comment = strdup(*contents);
  140.                         break;
  141.                 }
  142.                 DoMethod(data->LV_Server, MUIM_NList_Redraw, MUIV_NList_Redraw_Active);
  143.                 ServerListChanged = TRUE;
  144.             }
  145.             return NULL;
  146.             }
  147.         case NAVI_LOAD:
  148.             data = INST_DATA(cl, obj);
  149.             LoadServerList(data);
  150.             return NULL;
  151.         case NAVI_SAVE:
  152.             data = INST_DATA(cl, obj);
  153.             SaveServerList(data);
  154.             return NULL;
  155.         case NAVI_MARKSERVER:
  156.             data = INST_DATA(cl, obj);
  157.             MarkServerOnline(data, (char *)(((muimsg)msg)->arg1), (unsigned short)(((muimsg)msg)->arg2));
  158.             return NULL;
  159.         case NAVI_GETNAPIGATOR:
  160.             data = INST_DATA(cl, obj);
  161.             GetNapigatorList(data);
  162.             return NULL;
  163.     }
  164.     return(DoSuperMethodA(cl, obj, msg));
  165. }
  166.  
  167.  
  168. ULONG NavigatorNew(struct IClass *cl, Object *obj, struct opSet *msg)
  169. {
  170.     static const struct Hook ServerListDispHook = { {NULL, NULL}, &ServerListDisplay,  NULL, NULL };
  171.     static const struct Hook ServerListCompHook = { {NULL, NULL}, &ServerListCompare,  NULL, NULL };
  172.     static const struct Hook ServerListDestHook = { {NULL, NULL}, &ServerListDestruct, NULL, NULL };
  173.     static const struct Hook ServerStringHook   = { {NULL, NULL}, &ServerString,       NULL, NULL };
  174.  
  175.     struct NavigatorData *data;
  176.  
  177.     Object *LV_Server, *ST_Server, *ST_Port, *ST_Comment;
  178.     Object *BT_ConnectConnect, *BT_ConnectAdd, *BT_ConnectRemove, *BT_Update;
  179.  
  180.     if (obj = (Object *)DoSuperNew(cl, obj,
  181.         MUIA_HelpNode, "navi",
  182.         MUIA_Window_Title, MSG_NAVIGATOR_TITLE,
  183.         MUIA_Window_ID, MAKE_ID('N','A','V','I'),
  184.         WindowContents, VGroup,
  185.             Child, LV_Server = NListviewObject,
  186.                 MUIA_NList_Input, TRUE,
  187.                 MUIA_NListview_NList, NListObject,
  188.                     InputListFrame,
  189.                     MUIA_NList_ListBackground, MUII_ListBack,
  190.                     MUIA_NList_TitleBackground, MUII_ListBack,
  191.                     MUIA_NList_Title, TRUE,
  192.                     MUIA_NList_Format, "BAR,BAR,BAR,",
  193.                     MUIA_NList_DisplayHook, &ServerListDispHook,
  194.                     MUIA_NList_CompareHook2, &ServerListCompHook,
  195.                     MUIA_NList_DestructHook, &ServerListDestHook,
  196.                 End,
  197.             End,
  198.             Child, ColGroup(2),
  199.                 Child, Label2(MSG_NAVIGATOR_SERVER),
  200.                 Child, HGroup,
  201.                     Child, ST_Server = TextinputObject,
  202.                         StringFrame,
  203.                         MUIA_Textinput_Multiline, FALSE,
  204.                         MUIA_CycleChain, 1,
  205.                         MUIA_String_Accept, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-",
  206.                     End,
  207.                     Child, Label2(MSG_NAVIGATOR_PORT),
  208.                     Child, ST_Port = TextinputObject,
  209.                         StringFrame,
  210.                         MUIA_Textinput_Multiline, FALSE,
  211.                         MUIA_HorizWeight, 30,
  212.                         MUIA_String_Accept, "0123456789",
  213.                         MUIA_String_MaxLen, 6,
  214.                         MUIA_CycleChain, 1,
  215.                     End,
  216.                 End,
  217.                 Child, Label2(MSG_NAVIGATOR_COMMENT),
  218.                 Child, ST_Comment = TextinputObject,
  219.                     StringFrame,
  220.                     MUIA_Textinput_Multiline, FALSE,
  221.                     MUIA_CycleChain, 1,
  222.                 End,
  223.             End,
  224.             Child, RectangleObject,
  225.                 MUIA_FixHeight, 8,
  226.                 MUIA_Rectangle_HBar, TRUE,
  227.             End,
  228.             Child, HGroup,
  229.                 Child, BT_ConnectConnect = SimpleButton(MSG_NAVIGATOR_CONNECT_GAD),
  230.                 Child, BT_ConnectRemove  = SimpleButton(MSG_NAVIGATOR_REMOVE_GAD),
  231.                 Child, BT_ConnectAdd     = SimpleButton(MSG_NAVIGATOR_ADD_GAD),
  232.                 Child, HGroup,
  233.                     Child, BT_Update     = SimpleButton(MSG_NAVIGATOR_UPDATE_GAD),
  234.                         MUIA_ShortHelp, MSG_NAVIGATOR_UPDATE_HELP,
  235.                 End,
  236.             End,
  237.         End,
  238.         TAG_MORE, msg->ops_AttrList))
  239.     {
  240.         data = INST_DATA(cl, obj);
  241.         data->LV_Server  = LV_Server;
  242.         data->ST_Server  = ST_Server;
  243.         data->ST_Port    = ST_Port;
  244.         data->ST_Comment = ST_Comment;
  245.  
  246.         DoMethod(obj, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, obj, 3, MUIM_Set, MUIA_Window_Open, FALSE);
  247.  
  248.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_TitleClick,  MUIV_EveryTime, LV_Server, 4, MUIM_NList_Sort3, MUIV_TriggerValue, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_Both);
  249.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_TitleClick2, MUIV_EveryTime, LV_Server, 4, MUIM_NList_Sort3, MUIV_TriggerValue, MUIV_NList_SortTypeAdd_2Values, MUIV_NList_Sort3_SortType_2);
  250.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_SortType,    MUIV_EveryTime, LV_Server, 3, MUIM_Set, MUIA_NList_TitleMark,  MUIV_TriggerValue);
  251.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_SortType2,   MUIV_EveryTime, LV_Server, 3, MUIM_Set, MUIA_NList_TitleMark2, MUIV_TriggerValue);
  252.  
  253.         DoMethod(BT_ConnectConnect, MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, NAVI_CONNECT);
  254.         DoMethod(BT_ConnectRemove,  MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, NAVI_REMOVESERVER);
  255.         DoMethod(BT_ConnectAdd,     MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, NAVI_ADDSERVER);
  256.         DoMethod(BT_Update,         MUIM_Notify, MUIA_Pressed, FALSE, obj, 1, NAVI_GETNAPIGATOR);
  257.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_DoubleClick, MUIV_EveryTime, obj, 1, NAVI_CONNECT);
  258.  
  259.         LoadServerList(data);
  260.  
  261.         DoMethod(LV_Server, MUIM_Notify, MUIA_NList_Active, MUIV_EveryTime, obj, 1, NAVI_GETSERVER);
  262.  
  263.         set(ST_Server, MUIA_String_AttachedList, LV_Server);
  264.  
  265.         DoMethod(ST_Server,  MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, ST_Server, 4, MUIM_CallHook, &ServerStringHook, MUIV_TriggerValue, 0);
  266.         DoMethod(ST_Port,    MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, ST_Server, 4, MUIM_CallHook, &ServerStringHook, MUIV_TriggerValue, 1);
  267.         DoMethod(ST_Comment, MUIM_Notify, MUIA_String_Contents, MUIV_EveryTime, ST_Server, 4, MUIM_CallHook, &ServerStringHook, MUIV_TriggerValue, 2);
  268.  
  269.         return((ULONG)obj);
  270.     }
  271.     return(0);
  272. }
  273.  
  274.  
  275. void LoadServerList(struct NavigatorData *data)
  276. {
  277.     BPTR fh;
  278.     char buf[1024];
  279.     int line = 0;
  280.     struct ServerEntry *entry;
  281.     LONG argarray[] = { NULL, NULL, NULL, NULL };
  282.     UBYTE *argstr = "HOST/A,PORT/A/N,LASTUSED/A/N,COMMENT/K";
  283.     struct RDArgs *rdargs;
  284.  
  285.     if (fh = Open("PROGDIR:Amster.servers", MODE_OLDFILE)) {
  286.         set(data->LV_Server, MUIA_NList_Quiet, MUIV_NList_Quiet_Full);
  287.         if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
  288.             while (FGets(fh, buf, sizeof(buf))) {
  289.                 line++;
  290.                 
  291.                 rdargs->RDA_Buffer = NULL;
  292.                 rdargs->RDA_Source.CS_Buffer = buf;
  293.                 rdargs->RDA_Source.CS_Length = strlen(buf);
  294.                 rdargs->RDA_Source.CS_CurChr = 0;
  295.  
  296.                 argarray[3] = 0;
  297.                 if (ReadArgs(argstr, argarray, rdargs)) {
  298.                     if (entry = malloc(sizeof(struct ServerEntry))) {
  299.                         entry->Name = strdup((char *)argarray[0]);
  300.                         entry->Port = *((long *)argarray[1]);
  301.                         entry->LastOnline = *((long *)argarray[2]);
  302.                         if (argarray[3]) entry->Comment = strdup((char *)argarray[3]);
  303.                         else entry->Comment = strdup("");
  304.                         entry->Ping = -1;
  305.                         DoMethod(data->LV_Server, MUIM_NList_InsertSingle, entry, TAG_DONE);
  306.                     }
  307.                     FreeArgs(rdargs);
  308.                 }
  309.                 else gui_debugf((char *)MSG_PARSE_ERROR, "PROGDIR:Amster.servers", line);
  310.             }
  311.             FreeDosObject(DOS_RDARGS, rdargs);
  312.         }
  313.         set(data->LV_Server, MUIA_NList_Quiet, MUIV_NList_Quiet_None);
  314.         Close(fh);
  315.         DoMethod(data->LV_Server, MUIM_NList_Sort);
  316.     }
  317. }
  318.  
  319.  
  320. void SaveServerList(struct NavigatorData *data)
  321. {
  322.     struct ServerEntry *entry;
  323.     BPTR fh;
  324.     char buf[1024], *tmp;
  325.     int i;
  326.  
  327.     fh = Open("PROGDIR:Amster.servers", MODE_NEWFILE);
  328.     if (!fh) return;
  329.  
  330.     for (i=0; ; i++) {
  331.         DoMethod(data->LV_Server, MUIM_NList_GetEntry, i, &entry);
  332.         if (!entry) break;
  333.         if (entry->Comment && entry->Comment[0] != '\0') {
  334.             if (tmp = strrep(entry->Comment, "\"", "*\"")) {
  335.                 sprintf(buf, "%s %ld %ld COMMENT \"%s\"\n", entry->Name, entry->Port, entry->LastOnline, tmp);
  336.                 free(tmp);
  337.             }
  338.             else sprintf(buf, "%s %ld %ld\n", entry->Name, entry->Port, entry->LastOnline);
  339.         }
  340.         else sprintf(buf, "%s %ld %ld\n", entry->Name, entry->Port, entry->LastOnline);
  341.         Write(fh, buf, strlen(buf)); /* Should be buffered, check FWrite */
  342.     }
  343.  
  344.     Close(fh);
  345.     ServerListChanged = FALSE;
  346. }
  347.  
  348.  
  349. void MarkServerOnline(struct NavigatorData *data, char *server, unsigned short port)
  350. {
  351.     struct ServerEntry *entry=0;
  352.     int i;
  353.     BOOL new = FALSE;
  354.  
  355.     for (i=0; ; i++) {
  356.         DoMethod(data->LV_Server, MUIM_NList_GetEntry, i, &entry);
  357.         if (!entry) break;
  358.         if ((strcmp(server, entry->Name) == 0) && (port == entry->Port)) break;
  359.     }
  360.     if (!entry) {    /* Server not already on list */
  361.         if (prf->ServerList < 2) return;
  362.         if (entry = malloc(sizeof(struct ServerEntry))) {
  363.             entry->Name = strdup(server);
  364.             entry->Port = port;
  365.             entry->LastOnline = 0;    /* In case we don't succeed later on... */
  366.             entry->Comment = strdup("");
  367.             entry->Ping = -1;
  368.             new = TRUE;
  369.         }
  370.     }
  371.  
  372.     entry->LastOnline = GetDateStamp();
  373.     if (new)
  374.         DoMethod(data->LV_Server, MUIM_NList_InsertSingle, entry, MUIV_NList_Insert_Sorted);
  375.     else
  376.         DoMethod(data->LV_Server, MUIM_NList_Redraw, i);
  377.     ServerListChanged = TRUE;
  378. }
  379.  
  380.  
  381. MUI_LIST_DISP(ServerListDisplay, struct ServerEntry *entry)
  382. {
  383.     static struct DateTime dt;
  384.     static char buf[LEN_DATSTRING*2+6];
  385.     static char    buf2[20];
  386.     static char port[6];
  387.     static char datestring[LEN_DATSTRING];
  388.     static char timestring[LEN_DATSTRING];
  389.  
  390.     if (entry) {
  391.         *array++ = entry->Name;
  392.         sprintf(port, "%ld", entry->Port);
  393.         *array++ = port;
  394.         if (entry->LastOnline == 0) *array++ = "\33r-";
  395.         else {
  396.                 dt.dat_Stamp.ds_Days   = (entry->LastOnline)/(60*60*24);
  397.                 dt.dat_Stamp.ds_Minute = ((entry->LastOnline)%(60*60*24))/60;
  398.                 dt.dat_Stamp.ds_Tick   = ((entry->LastOnline)%60)*TICKS_PER_SECOND;
  399.                 dt.dat_Format = FORMAT_DOS;
  400.                 dt.dat_Flags = DTF_SUBST;
  401.                 dt.dat_StrDay = NULL;
  402.                 dt.dat_StrDate = datestring;
  403.                 dt.dat_StrTime = timestring;
  404.                 if (DateToStr(&dt)) {
  405.                     sprintf(buf, "\33r%s %s", datestring, timestring);
  406.                     *array++ = buf;
  407.                 }
  408.                 else *array++ = "\33r-";
  409.         }
  410.         *array++ = entry->Comment;
  411.  
  412.         if (entry->Ping >= 0) {
  413.             sprintf(buf2, "%ld", entry->Ping);
  414.             *array   = buf2;
  415.         }
  416.         else *array = "-";
  417.     }
  418.     else {
  419.         *array++ = (char *)MSG_NAVIGATOR_LIST_SERVER;
  420.         *array++ = (char *)MSG_NAVIGATOR_LIST_PORT;
  421.         *array++ = (char *)MSG_NAVIGATOR_LIST_LASTONLINE;
  422.         *array++ = (char *)MSG_NAVIGATOR_LIST_COMMENT;
  423.         *array   = (char *)MSG_NAVIGATOR_LIST_PING;
  424.     }
  425.  
  426.     return 0;
  427. }
  428.  
  429.  
  430. MUI_NLIST_COMP(ServerListCompare)
  431. {
  432.     struct ServerEntry *entry1 = ncm->entry1;
  433.     struct ServerEntry *entry2 = ncm->entry2;
  434.     LONG col1 = ncm->sort_type & MUIV_NList_TitleMark_ColMask;
  435.     LONG col2 = ncm->sort_type2 & MUIV_NList_TitleMark2_ColMask;
  436.     ULONG result = 0;
  437.  
  438.     if (ncm->sort_type == MUIV_NList_SortType_None) return (0);
  439.  
  440.     if (col1 == 0) {
  441.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  442.             result = (LONG) stricmp(entry2->Name, entry1->Name);
  443.         else
  444.             result = (LONG) stricmp(entry1->Name, entry2->Name);
  445.     }
  446.     else if (col1 == 1) {
  447.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  448.             result = entry2->Port - entry1->Port;
  449.         else
  450.             result = entry1->Port - entry2->Port;
  451.     }
  452.     else if (col1 == 2) {
  453.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  454.             result = entry2->LastOnline - entry1->LastOnline;
  455.         else
  456.             result = entry1->LastOnline - entry2->LastOnline;
  457.     }
  458.     else if (col1 == 3) {
  459.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  460.             result = (LONG) stricmp(entry2->Comment, entry1->Comment);
  461.         else
  462.             result = (LONG) stricmp(entry1->Comment, entry2->Comment);
  463.     }
  464.     else if (col1 == 4) {
  465.         if (ncm->sort_type & MUIV_NList_TitleMark_TypeMask)
  466.             result = entry2->Ping - entry1->Ping;
  467.         else
  468.             result = entry1->Ping - entry2->Ping;
  469.     }
  470.  
  471.     if ((result != 0) || (col1 == col2)) return (result);
  472.  
  473.     if (col2 == 0) {
  474.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  475.             result = (LONG) stricmp(entry2->Name, entry1->Name);
  476.         else
  477.             result = (LONG) stricmp(entry1->Name, entry2->Name);
  478.     }
  479.     else if (col2 == 1) {
  480.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  481.             result = entry2->Port - entry1->Port;
  482.         else
  483.             result = entry1->Port - entry2->Port;
  484.     }
  485.     else if (col2 == 2) {
  486.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  487.             result = entry2->LastOnline - entry1->LastOnline;
  488.         else
  489.             result = entry1->LastOnline - entry2->LastOnline;
  490.     }
  491.     else if (col2 == 3) {
  492.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  493.             result = (LONG) stricmp(entry2->Comment, entry1->Comment);
  494.         else
  495.             result = (LONG) stricmp(entry1->Comment, entry2->Comment);
  496.     }
  497.     else if (col2 == 4) {
  498.         if (ncm->sort_type & MUIV_NList_TitleMark2_TypeMask)
  499.             result = entry2->Ping - entry1->Ping;
  500.         else
  501.             result = entry1->Ping - entry2->Ping;
  502.     }
  503.  
  504.     return (result);
  505. }
  506.  
  507.  
  508. MUI_LIST_DEST(ServerListDestruct, struct ServerEntry *entry)
  509. {
  510.     free(entry);
  511.     return 0;
  512. }
  513.  
  514.  
  515. MUI_HOOK(ServerString, Object *lala, APTR *contents)
  516. {
  517.     DoMethod(gui->WI_Navigator, NAVI_REDRAWSERVER, contents);
  518.     return 0;
  519. }
  520.  
  521. /* The rest of this file is pure, buggy, untested, experimental crap */
  522.  
  523. BOOL GetNapigatorList(struct NavigatorData *data)
  524. {
  525.     char *buffer;
  526.     int s;
  527.     struct sockaddr_in sin;
  528.     struct sockaddr *sa;
  529.     struct hostent *he;
  530.     BOOL HasBase;
  531.  
  532. #ifdef AMSTER_DEBUG
  533. gui_debug("1");
  534. #endif
  535.     if (!SocketBase) {
  536.         if (!(SocketBase = OpenLibrary("bsdsocket.library", 0))) return FALSE;
  537.         HasBase = FALSE;
  538.     }
  539.     else HasBase = TRUE;
  540.  
  541. #ifdef AMSTER_DEBUG
  542. gui_debugf("2, base: %ld", SocketBase);
  543. #endif
  544.     he = gethostbyname("napigator.com");
  545.     if (he == NULL) {
  546.         if (!HasBase) {
  547.             CloseLibrary(SocketBase);
  548.             SocketBase = NULL;
  549.         }
  550.         return FALSE;
  551.     }
  552.  
  553. #ifdef AMSTER_DEBUG
  554. gui_debugf("3, he: %ld, he->h_addr: %ld", he, he->h_addr);
  555. #endif
  556.  
  557. /*    bzero(&sin, sizeof(sin));*/
  558.     sin.sin_family = AF_INET;
  559.     sin.sin_len = sizeof(sin);
  560. /*    memcpy(&sin.sin_addr, he->h_addr, he->h_length);*/
  561.     sin.sin_addr.s_addr = *(long *)he->h_addr_list[0];
  562.     sin.sin_port = htons(80);
  563.     sa = (struct sockaddr *) &sin;
  564.  
  565. #ifdef AMSTER_DEBUG
  566. gui_debug("4");
  567. #endif
  568.     s = socket(AF_INET, SOCK_STREAM, 0);
  569.     if (s < 0) {
  570.         if (!HasBase) {
  571.             CloseLibrary(SocketBase);
  572.             SocketBase = NULL;
  573.         }
  574.         return FALSE;
  575.     }
  576.  
  577. #ifdef AMSTER_DEBUG
  578. gui_debug("5");
  579. #endif
  580.     if (connect(s, sa, sa->sa_len) < 0) {
  581.         CloseSocket(s);
  582.         if (!HasBase) {
  583.             CloseLibrary(SocketBase);
  584.             SocketBase = NULL;
  585.         }
  586.         return FALSE;
  587.     }
  588.  
  589. #ifdef AMSTER_DEBUG
  590. gui_debug("6");
  591. #endif
  592.     if (send(s, NAPIGATOR_REQ, sizeof(NAPIGATOR_REQ), 0) != sizeof(NAPIGATOR_REQ)) {
  593.         CloseSocket(s);
  594.         if (!HasBase) {
  595.             CloseLibrary(SocketBase);
  596.             SocketBase = NULL;
  597.         }
  598.         return FALSE;
  599.     }
  600.  
  601.     if (!(buffer = malloc(131072))) {
  602.         CloseSocket(s);
  603.         if (!HasBase) {
  604.             CloseLibrary(SocketBase);
  605.             SocketBase = NULL;
  606.         }
  607.     }
  608.  
  609. #ifdef AMSTER_DEBUG
  610. gui_debug("7");
  611. #endif
  612.     if (get_response(s, buffer, 131072)) {
  613. /*printf("%s", buffer);*/
  614.         UpdateFromNapigator(data, buffer);
  615.     }
  616.  
  617. #ifdef AMSTER_DEBUG
  618. gui_debug("8");
  619. #endif
  620.     CloseSocket(s);
  621.     if (!HasBase) {
  622.         CloseLibrary(SocketBase);
  623.         SocketBase = NULL;
  624.     }
  625.     free(buffer);
  626.  
  627.     return TRUE;
  628. }
  629.  
  630.  
  631. BOOL get_response(long sockfd, char *buf, int max)
  632. {
  633.     int len = 0, le;
  634.  
  635.     while (len < max-1) {
  636.         le = recv(sockfd, buf+len, max-len-1, 0);
  637.         if (le == 0) {
  638.             buf[len] = '\0';
  639.             return TRUE;
  640.         }
  641.         if (le < 0) {
  642.             return FALSE;
  643.         }
  644.         len += le;
  645.     }
  646.     buf[max-1] = '\0';
  647.  
  648.     return TRUE;
  649. }
  650.  
  651.  
  652. void UpdateFromNapigator(struct NavigatorData *data, char *list)
  653. {
  654.     char *p, *buf;
  655.     int size = strlen(list);
  656.     int i;
  657.     LONG argarray[] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  658.     UBYTE *argstr = "SERVER/A,PORT/A/N,NETWORK/A,USERS/A/N,SONGS/A/N,GBYTES/A/N,COMMENT/A";
  659.     struct RDArgs *rdargs;
  660.  
  661.     /* Divide it into substrings */
  662.     for (i = 0; i < size; i++) {
  663.         if (list[i] == '\n') list[i] = '\0';
  664.     }
  665.  
  666.     i = 0;
  667.  
  668.     if (rdargs = AllocDosObject(DOS_RDARGS, NULL)) {
  669.         while (i < size) {
  670.             p = list+i;
  671.  
  672.             buf = malloc(strlen(p)+2);
  673.             strcpy(buf, p);
  674.             buf[strlen(p)] = '\n';
  675.             buf[strlen(p)+1] = '\0';
  676.  
  677.             rdargs->RDA_Buffer = NULL;
  678.             rdargs->RDA_Source.CS_Buffer = buf;
  679.             rdargs->RDA_Source.CS_Length = strlen(buf);
  680.             rdargs->RDA_Source.CS_CurChr = 0;
  681.  
  682.             if (ReadArgs(argstr, argarray, rdargs)) {
  683.                 NapigatorAdd(data, argarray);
  684.                 FreeArgs(rdargs);
  685.             }
  686.  
  687.             free(buf);
  688.  
  689.             i += strlen(p);
  690.             if (list[i] == '\0') i++;
  691.         }
  692.         FreeDosObject(DOS_RDARGS, rdargs);
  693.     }
  694. }
  695.  
  696.  
  697. void NapigatorAdd(struct NavigatorData *data, LONG argarray[])
  698. {
  699.     struct ServerEntry *entry;
  700.     BOOL found = FALSE;
  701.     int j, total;
  702.     u_long tmp;
  703.  
  704.     GetAttr(MUIA_NList_Entries, data->LV_Server, &tmp);
  705.     total = tmp;
  706.  
  707.     j = 0;
  708.     while (j<total && !found) {
  709.         DoMethod(data->LV_Server, MUIM_NList_GetEntry, j, &entry);
  710.         if (entry) {
  711.             if (strcmp((char *)argarray[0], entry->Name) == 0 && *((long *)argarray[1]) == entry->Port) found = TRUE;
  712.         }
  713.         j++;
  714.     }
  715.  
  716.     if (!found) {    /* Server not already on list */
  717.         if (entry = malloc(sizeof(struct ServerEntry))) {
  718.             entry->Name = strdup((char *)argarray[0]);
  719.             entry->Port = *((long *)argarray[1]);
  720.             entry->LastOnline = 0;
  721.             entry->Comment = malloc(strlen((char *)argarray[2]) + strlen((char *)argarray[6]) + 3);
  722.             sprintf(entry->Comment, "%s; %s", (char *)argarray[2], (char *)argarray[6]);
  723.             DoMethod(data->LV_Server, MUIM_NList_InsertSingle, entry, MUIV_NList_Insert_Bottom);
  724.             ServerListChanged = TRUE;
  725.         }
  726.     }
  727.  
  728. }
  729.  
  730.  
  731. /*
  732. ssize_t readline(int fd, void *vptr, size_t maxlen)
  733. {
  734.     ssize_t n, rc;
  735.     char c, *ptr;
  736.  
  737.     ptr = vptr;
  738.     for (n = 1; n < maxlen; n++) {
  739.         again:
  740.         if ((rc = read(fd, &c, 1)) == 1) {
  741.             *ptr++ = c;
  742.             if (c == '\n')
  743.                 break;
  744.         } else if (rc == 0) {
  745.         
  746. }
  747. */
  748.